package test;

import instance.InstanceResultado;
import instance.InstanceTP3;

import java.util.Collections;
import java.util.LinkedList;
import java.util.Random;

public class Generadores_de_Grafos {
	public static LinkedList<InstanceTP3> generarGrafosRandom(int max, int grafos_por_n) {
		/* Genera grafos con cantidad de nodos desde 5 hasta max */
		LinkedList<InstanceTP3> res = new LinkedList<InstanceTP3>();
		Random rnd = new Random();
		for (int n = 5; n <= max; n++) {
			for (int k = 0; k < grafos_por_n; k++) {
				int[][] matriz = new int[n][n];
				for (int i = 1; i < n; i++) {
					for (int j = 0; j < i; j++) {
						matriz[i][j] = rnd.nextInt(5000);
						matriz[j][i] = matriz[i][j];
					}
				}
				res.add(new InstanceTP3(n, rnd.nextInt(n), matriz));
			}
		}
		return res;
	}

	public static LinkedList<InstanceTP3> generarGrafosRandomEspecificados(int[] tamano_grafos, int grafos_por_n) {
		/* Genera, para cada elemento del arreglo, "grafos_por_n" grafos random */
		LinkedList<InstanceTP3> res = new LinkedList<InstanceTP3>();
		Random rnd = new Random();
		int cant_grafos_entrada = tamano_grafos.length;
		for (int cant_n = 0; cant_n < cant_grafos_entrada; cant_n++) {
			for (int k = 0; k < grafos_por_n; k++) {
				int[][] matriz = new int[tamano_grafos[cant_n]][tamano_grafos[cant_n]];
				for (int i = 1; i < tamano_grafos[cant_n]; i++) {
					for (int j = 0; j < i; j++) {
						matriz[i][j] = rnd.nextInt(5000);
						matriz[j][i] = matriz[i][j];
					}
				}
				res.add(new InstanceTP3(tamano_grafos[cant_n], rnd.nextInt(tamano_grafos[cant_n]), matriz));
			}
		}
		return res;
	}

	public static LinkedList<InstanceTP3> generarGrafosRandom2(int max,
			int grafos_por_n) {
		/* Genera grafos con cantidad de nodos desde 5 hasta max */
		LinkedList<InstanceTP3> res = new LinkedList<InstanceTP3>();
		Random rnd = new Random();
		for (int n = max; n <= max; n++) {
			for (int k = 0; k < grafos_por_n; k++) {
				int[][] matriz = new int[n][n];
				for (int i = 1; i < n; i++) {
					for (int j = 0; j < i; j++) {
						matriz[i][j] = rnd.nextInt(5000);
						matriz[j][i] = matriz[i][j];
					}
				}
				res.add(new InstanceTP3(n, 0, matriz));
			}
		}
		return res;
	}

	public static LinkedList<InstanceTP3> generarGrafosRandomIntercalado(
			int max, int cual_empezar, int cuantos) {
		/*
		 * Genera "cuantos" (pasado como parámetro) grafos con cantidad de nodos
		 * desde "cual_empezar" hasta max
		 */
		LinkedList<InstanceTP3> res = new LinkedList<InstanceTP3>();
		Random rnd = new Random();
		int cuanto_sumar = (max-cual_empezar) / cuantos;
		for (int n = cual_empezar; n <= max; n += cuanto_sumar) {
			int[][] matriz = new int[n][n];
			for (int i = 1; i < n; i++) {
				for (int j = 0; j < i; j++) {
					matriz[i][j] = rnd.nextInt(5000);
					matriz[j][i] = matriz[i][j];
				}
			}
			res.add(new InstanceTP3(n, rnd.nextInt(n), matriz));
		}
		return res;
	}
	
	public static LinkedList<InstanceTP3> generarGrafosRandomEnIntervalo(
			int max, int cual_empezar, int cuantos) {
		/*
		 * Genera grafos con n random entre "cual_empezar" y "max", tantos como diga "cuantos".
		 */
		LinkedList<InstanceTP3> res = new LinkedList<InstanceTP3>();
		Random rnd = new Random();
		for (int k = 0; k <= cuantos; k++) {
			int n = rnd.nextInt(max-cual_empezar+1)+cual_empezar; 
			int[][] matriz = new int[n][n];
			for (int i = 1; i < n; i++) {
				for (int j = 0; j < i; j++) {
					matriz[i][j] = rnd.nextInt(5000);
					matriz[j][i] = matriz[i][j];
				}
			}
			res.add(new InstanceTP3(n, rnd.nextInt(n), matriz));
		}
		return res;
	}

	public static LinkedList<InstanceTP3> generarGrafoAscendente(int max,
			int grafos_por_n) {
		/* Genera grafos con cantidad de nodos desde 4 hasta max */
		LinkedList<InstanceTP3> res = new LinkedList<InstanceTP3>();
		Random rnd = new Random();
		int peso_anterior = rnd.nextInt(50);
		for (int n = 5; n <= max; n++) {
			for (int k = 0; k < grafos_por_n; k++) {
				int[][] matriz = new int[n][n];
				for (int i = 1; i < n; i++) {
					for (int j = 0; j < i; j++) {
						peso_anterior += rnd.nextInt(50) + 1;
						matriz[i][j] = peso_anterior;
						matriz[j][i] = matriz[i][j];
					}
				}
				res.add(new InstanceTP3(n, rnd.nextInt(n), matriz));
			}
		}
		return res;
	}

	public static LinkedList<InstanceTP3> generarGrafoDescendente(int max,
			int grafos_por_n) {
		/* Genera grafos con cantidad de nodos desde 4 hasta max */
		LinkedList<InstanceTP3> res = new LinkedList<InstanceTP3>();
		Random rnd = new Random();
		int peso_anterior = rnd.nextInt(50);
		for (int n = 5; n <= max; n++) {
			for (int k = 0; k < grafos_por_n; k++) {
				int[][] matriz = new int[n][n];
				for (int i = n - 1; i >= 0; i--) {
					for (int j = i - 1; j >= 0; j--) {
						peso_anterior += rnd.nextInt(50) + 1;
						matriz[i][j] = peso_anterior;
						matriz[j][i] = matriz[i][j];
					}
				}
				res.add(new InstanceTP3(n, rnd.nextInt(n), matriz));
			}
		}
		return res;
	}

	public static InstanceResultado generarSolucionMala(InstanceTP3 inst) {
		/* Genera grafos con cantidad de nodos desde 5 hasta max */
		LinkedList<Integer> input = new LinkedList<Integer>();
		for (int i = 0; i < inst.getN(); i++)
			input.add(i);
		input.removeFirstOccurrence(inst.getNodo_origen());
		Collections.shuffle(input);
		Random rnd = new Random();
		int long_primero = 2 + rnd.nextInt(inst.getN() - 3 - 2 + 1);
		LinkedList<Integer> primer_ciclo = new LinkedList<Integer>();
		for (int i = 0; i < long_primero; i++)
			primer_ciclo.add(input.pollFirst());
		InstanceResultado res = new InstanceResultado(primer_ciclo, input,
				inst.nodo_origen);
		return res;
	}

}
